﻿#ifndef CUSTOM_BRDF_INCLUDED
#define CUSTOM_BRDF_INCLUDED

//BRDF：Bidirectional Reflectance Distribution Function（双向反射分布函数）

#define MIN_REFLECTIVITY 0.04 //最小反射率

//BRDF Properties
struct BRDF
{
    float3 diffuse; //漫反射
    float3 specular; //镜面反射
    float roughness; //粗糙度
};

//1 - 反射率（金属度越高，镜面反射越强，根据能量守恒，漫反射越弱）
float OneMinusReflectivity(float metallic)
{
    float range = 1.0 - MIN_REFLECTIVITY; //0.96
    return range - metallic * range;
}

//获取 BRDF 参数
BRDF GetBRDF(Surface surface,bool applyAlphaToDiffuse = false)
{
    BRDF brdf;

    float oneMinusReflectivity = OneMinusReflectivity(surface.metallic); //1 - 反射率
    brdf.diffuse = surface.color * oneMinusReflectivity;
    if(applyAlphaToDiffuse)
    {
        brdf.diffuse *= surface.alpha; //Diffuse 预乘 Alpha（光线会穿透 透明物体，所以Diffuse会减小）
    }
    brdf.specular = lerp(MIN_REFLECTIVITY,surface.color,surface.metallic);//surface.color - brdf.diffuse; //Energy Conservation
    float perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(surface.smoothness); //将光滑度转为粗糙度
    brdf.roughness = PerceptualRoughnessToRoughness(perceptualRoughness); //转为Disney光照模型的粗糙度
    return brdf; //初始是一个 完美的漫反射
}

//使用BRDF计算镜面反射强度
float SpecularStrength(Surface surface,BRDF brdf,Light light)
{
    float3 h = SafeNormalize(light.direction + surface.viewDirection); // H = normalize(L + V)
    float nh2 = Square(saturate(dot(surface.normal, h)));
    float lh2 = Square(saturate(dot(light.direction, h)));
    float r2 = Square(brdf.roughness);
    float d2 = Square(nh2 * (r2 - 1.0) + 1.00001); // d = (N*H)2 * (r2 - 1) + 1.00001
    float normalization = brdf.roughness * 4.0 + 2.0;
    return r2 / (d2 * max(0.1, lh2) * normalization); // = r2/(d2*max(0.1,(L*H)2)*n)
}
//使用BRDF计算直接光照
float3 DirectBRDF(Surface surface,BRDF brdf,Light light)
{
    return SpecularStrength(surface,brdf,light) * brdf.specular + brdf.diffuse;
}

#endif